package com.quectel.cms.controller.merchant;


import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.quectel.cms.controller.BaseController;
import com.quectel.cms.vo.merchant.MerchantDetailVo;
import com.quectel.constant.global.SystemConstants;
import com.quectel.constant.global.annotation.RequirePermissions;
import com.quectel.core.module.merchant.dto.MerchantDto;
import com.quectel.core.module.merchant.service.MerchantService;
import com.quectel.pay.module.merchant.dto.PayCertFileDto;
import com.quectel.pay.module.merchant.dto.PayChannelDto;
import com.quectel.pay.module.merchant.service.PayCertFileService;
import com.quectel.pay.module.merchant.service.PayChannelService;
import com.quectel.util.common.CopyUtils;
import com.quectel.util.common.Page;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @author ryan
 * @email ryan.ran@quectel.com
 * @date 2023/03/28 13:09
 */
@RestController
@RequestMapping("merchant")
@Tag(name = "MerchantController", description = "商户表相关api")
public class MerchantController extends BaseController {

    @DubboReference
    private MerchantService merchantService;
    @DubboReference
    private PayChannelService payChannelService;
    @DubboReference
    private PayCertFileService payCertFileService;

    /**
     * 删除channel配置
     *
     * @param channelId
     * @return
     */
    @PostMapping("deleteChannel")
    @RequirePermissions(values = "merchant:delete")
    @Operation(summary = "删除channel配置")
    public Response<Object> deleteChannel(@RequestBody Long channelId) {

        PayChannelDto payChannelDto = payChannelService.selectById(channelId);
        if (payChannelDto != null) {
            Map<String, Object> params = new HashMap<>();
            super.fillAuthorityData(params);

            params.remove(SystemConstants.ENTITY_ID_FLAG);
            params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(payChannelDto.getMchId()));

            if (merchantService.queryTotal(params) <= 0) {
                return Response.error(SystemConstants.ILLEGAL_MSG);
            }

            payChannelService.deleteBatch(new Long[]{channelId});
        }

        return Response.ok();
    }

    /**
     * 根据小区获取商户列表
     *
     * @param villageId
     * @return
     */
    @GetMapping("queryAll")
    @RequirePermissions(values = "merchant:list")
    @Operation(summary = "根据小区获取商户列表")
    public Response<List<MerchantDto>> merchantConfList(
            @Parameter(description = "小区id", required = true) @RequestParam Long villageId
    ) {
        Request request = Request.configParamsNotPage(Request.parseParams(httpServletRequest));
        super.fillAuthorityData(request.getParams());

        List<MerchantDto> merchantDtos = merchantService.selectByVillageId(villageId);
        return Response.<List<MerchantDto>>ok().wrap(merchantDtos);
    }

    /**
     * 证书上传
     *
     * @param request
     * @return
     */
    @PostMapping("uploadCert")
    public Response uploadCert(MultipartHttpServletRequest request) {
        Iterator<String> fileNames = request.getFileNames();
        while (fileNames.hasNext()) {
            String next = fileNames.next();
            List<MultipartFile> files = request.getFiles(next);
            for (MultipartFile file : files) {

                try (InputStream in = file.getInputStream()) {
                    byte[] bytes = IOUtils.toByteArray(in);

                    String sha1Code = HexUtil.encodeHexStr(DigestUtil.sha1(bytes));
                    PayCertFileDto payCertFileDto = payCertFileService.selectByCode(sha1Code);
                    if (payCertFileDto == null) {

                        String base64Data = Base64.getEncoder().encodeToString(bytes);
                        String filename = file.getOriginalFilename();

                        payCertFileDto = new PayCertFileDto();
                        payCertFileDto.setSha1Code(sha1Code);
                        payCertFileDto.setFileName(filename);
                        payCertFileDto.setFileBase64Date(base64Data);
                        payCertFileDto.setCreateTime(new Date());
                        Long id = payCertFileService.save(payCertFileDto);
                        payCertFileDto.setId(id);
                    }
                    return Response.ok().wrap(payCertFileDto.getId());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Response.error("上传失败");
    }

    /**
     * 分页查询
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("list")
    @RequirePermissions(values = "merchant:list")
    @Operation(summary = "分页列表")
    public Response<Page<MerchantDto>> list(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {
        //查询列表数据
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        super.fillAuthorityData(request.getParams());
        int total = merchantService.queryTotal(request.getParams());

        List<MerchantDto> list = null;
        if (total > 0) {
            list = merchantService.queryList(request.getParams());
        } else {
            list = new ArrayList<>();
        }

        Map<String, Object> queryChannelMap = new HashMap<>();
        for (MerchantDto merchantDto : list) {
            queryChannelMap.put(LambdaUtil.getFieldName(PayChannelDto::getMchId), merchantDto.getId());
            int channelTotal = payChannelService.queryTotal(queryChannelMap);
            merchantDto.setChannelCount(channelTotal);
        }

        Page<MerchantDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<MerchantDto>>ok().wrap(page);
    }

    /**
     * 编辑查询反显
     *
     * @param id
     * @return
     */
    @GetMapping("infoForEdit/{id}")
    @RequirePermissions(values = "merchant:edit")
    @Operation(summary = "查询单条记录")
    public Response<MerchantDetailVo> infoForEdit(@PathVariable("id") Long id, @RequestParam Byte type) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (merchantService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        MerchantDto merchantDto = merchantService.selectById(id);
        MerchantDetailVo merchantDetailVo = CopyUtils.copyObj(merchantDto, MerchantDetailVo.class);

        List<PayChannelDto> payChannelDtos = payChannelService.queryListByMchId(merchantDto.getId(), Boolean.TRUE);

        PayChannelDto payChannelDto = payChannelDtos.parallelStream().filter(o -> o.getPayType().equals(type)).findFirst().orElse(null);
        merchantDetailVo.setPayChannel(payChannelDto);
        return Response.<MerchantDetailVo>ok().wrap(merchantDetailVo);
    }

    /**
     * 详情
     *
     * @param id
     * @return
     */
    @GetMapping("info/{id}")
    @RequirePermissions(values = "merchant:info")
    @Operation(summary = "查询单条记录")
    public Response<MerchantDetailVo> info(@PathVariable("id") Long id, @RequestParam Byte type) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (merchantService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        MerchantDto merchantDto = merchantService.selectById(id);
        MerchantDetailVo merchantDetailVo = CopyUtils.copyObj(merchantDto, MerchantDetailVo.class);

        List<PayChannelDto> payChannelDtos = payChannelService.queryListByMchId(merchantDto.getId(), Boolean.TRUE);

        PayChannelDto payChannelDto = payChannelDtos.parallelStream().filter(o -> o.getPayType().equals(type)).findFirst().orElse(null);
        merchantDetailVo.setPayChannel(payChannelDto);
        return Response.<MerchantDetailVo>ok().wrap(merchantDetailVo);
    }

    /**
     * 保存
     *
     * @param merchantDetailVo
     * @return
     */
    @PostMapping("save")
    @RequirePermissions(values = "merchant:edit")
    @Operation(summary = "保存单条记录")
    public Response<Object> save(@RequestBody @Validated MerchantDetailVo merchantDetailVo) {
        List<MerchantDto> merchantDtos = merchantService.selectByVillageId(merchantDetailVo.getVillageId());
        if (merchantDtos.parallelStream().anyMatch(o -> o.getName().equals(merchantDetailVo.getName()))) {
            return Response.error("商户名不能重复");
        }
        MerchantDto merchantDto = CopyUtils.copyObj(merchantDetailVo, MerchantDto.class);
        //填充基础数据
        fillSaveCommonData(merchantDto);

        try {
            Long mchId = merchantService.save(merchantDto);

            payChannelService.saveOrUpdate(mchId, Collections.singletonList(merchantDetailVo.getPayChannel()));

            return Response.ok().wrap(mchId);
        } catch (Exception e) {
            logger.warn("Create merchant error. ", e);
        }
        return Response.error("商户新增异常");
    }


    /**
     * 修改
     *
     * @param merchantDetailVo
     * @return
     */
    @PostMapping("update")
    @RequirePermissions(values = "merchant:edit")
    @Operation(summary = "修改单条记录")
    public Response<Object> update(@RequestBody @Validated MerchantDetailVo merchantDetailVo) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(merchantDetailVo.getId()));
        if (merchantService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        List<MerchantDto> merchantDtos = merchantService.selectByVillageId(merchantDetailVo.getVillageId());
        if (merchantDtos.parallelStream()
                .filter(o -> !o.getId().equals(merchantDetailVo.getId()))
                .anyMatch(o -> o.getName().equals(merchantDetailVo.getName()))) {
            return Response.error("商户名不能重复");
        }

        MerchantDto merchantDto = CopyUtils.copyObj(merchantDetailVo, MerchantDto.class);
        //填充基础数据
        fillEditCommonData(merchantDto);

        try {
            merchantService.updateById(merchantDto);

            payChannelService.saveOrUpdate(merchantDto.getId(), Collections.singletonList(merchantDetailVo.getPayChannel()));

            return Response.ok().wrap(merchantDetailVo.getId());
        } catch (Exception e) {
            logger.warn("Update merchant error. ", e);
        }
        return Response.error("商户修改异常");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @PostMapping("delete")
    @RequirePermissions(values = "merchant:delete")
    @Operation(summary = "批量删除记录")
    public Response<Object> delete(@RequestBody Long[] ids) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);

        for (Long id : ids) {

            params.remove(SystemConstants.ENTITY_ID_FLAG);
            params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));

            if (merchantService.queryTotal(params) <= 0) {
                return Response.error(SystemConstants.ILLEGAL_MSG);
            }
        }

        merchantService.deleteBatch(ids);

        return Response.ok();
    }
}
